#include "AC33Mxxx_conf.h"
#include "driver_header.h"

SYSTEM_CLOCK_INFO		gSysClockInfo; 




/**
************************************************************************************
* @ Name : Init_SystemClock
*
* @ Parameter
*		none
*
*
************************************************************************************
*/
void Init_SystemClock (void)
{
	volatile UINT32		reg_val; 
	volatile UINT32		delay; 
	UINT32				hclk_info, pclk_info; 


	//------------------------------------------------------------------------------------------
	// set CLKO
	//
	//				COR			@ address = 0x4000_0050
	//
	//
	//------------------------------------------------------------------------------------------
	// CLKO
	//
	//				CLKO = MCLK						if CLKODIV == 0
	//				CLKO = MCLK / (CLKODIV * 2)		if CLKODIV != 0
	//
	//
	//------------------------------------------------------------------------------------------
	reg_val = CSP_SCU_GET_COR(SCU);
	reg_val &= ~COR_MASK; 
	reg_val |= (COR_CLKOEN|0x0004); 		// PCLK/10
	CSP_SCU_SET_COR(SCU, reg_val); 



	//------------------------------------------------------------------------------------------
	// select RINGOSC as main clock 
	//
	//				CSCR		@ address = 0x4000_0040
	//				SCCR		@ address = 0x4000_0044
	//
	//
	//------------------------------------------------------------------------------------------
	CSP_SCU_SET_CSCR(SCU, CSCR_RINGOSCCON_ENABLE); 
	CSP_SCU_SET_SCCR(SCU, SCCR_MCLKSEL_INTERNAL_RINGOSC); 



	//------------------------------------------------------------------------------------------
	// HCLK = PCLK = main clock 
	//
	//
	//------------------------------------------------------------------------------------------

	
	//------------------------------------------------------------------------------------------
	// turn IOSC 20M & XTAL 4, 8M 
	//
	//				CSCR		@ address = 0x4000_0040
	//
	//
	//------------------------------------------------------------------------------------------
	// Assumption
	//
	//				XTAL pin setting is already done.
	//
	//------------------------------------------------------------------------------------------
	reg_val = CSP_SCU_GET_CSCR(SCU); 
	reg_val |= (CSCR_IOSCCON_ENABLE|CSCR_EOSCON_ENABLE); 
	CSP_SCU_SET_CSCR(SCU, reg_val); 



	//------------------------------------------------------------------------------------------
	// monitor XTAL 
	//
	//				CMR			@ address = 0x4000_0048
	//
	//
	//------------------------------------------------------------------------------------------
	reg_val = CSP_SCU_GET_CMR(SCU);
	reg_val &= ~CMR_EOSC_MASK; 
	reg_val |= (CMR_EOSCMNT); 
	CSP_SCU_SET_CMR(SCU, reg_val); 

	while ((CSP_SCU_GET_CMR(SCU) & CMR_EOSCSTS) != CMR_EOSCSTS); 



	//------------------------------------------------------------------------------------------
	// select IOSC 20M as main clock 
	//
	//				CSCR		@ address = 0x4000_0040
	//				SCCR		@ address = 0x4000_0044
	//
	//
	//------------------------------------------------------------------------------------------
	reg_val = CSP_SCU_GET_SCCR(SCU); 
	reg_val &= ~SCCR_MASK; 
	reg_val |= (SCCR_FINSEL_MOSC|SCCR_MCLKSEL_PLL_BYPASS); 
	CSP_SCU_SET_SCCR(SCU, reg_val); 



	//------------------------------------------------------------------------------------------
	// PLL Setting (RealChip)
	//
	//				PLLCON		@ address = 0x4000_0060
	//
	//------------------------------------------------------------------------------------------
	//				PLLCON [8:0]	0x150	72MHz
	//								0x140	64MHz
	//								0x130	48MHz
	//								0x141	32MHz
	//								0x121	20MHz
	//								0x132	16MHz
	//------------------------------------------------------------------------------------------
	
#ifdef SYSTEM_HCLK_72M_PCLK_72M

	CSP_SCU_PLLEnable (SCU, XTAL8M_INPUT, PLLCON_PREDIV_DIV_BY_2, PLLCON_FBCTRL_18, 0); 	// (8/2 * 18)/1 = 72

	hclk_info = 72000000;
	pclk_info = 72000000; 
	
#elif defined (SYSTEM_HCLK_64M_PCLK_64M)

	CSP_SCU_PLLEnable (SCU, XTAL8M_INPUT, PLLCON_PREDIV_DIV_BY_2, PLLCON_FBCTRL_16, 0); 	// (8/2 * 16)/1 = 64

	hclk_info = 64000000;
	pclk_info = 64000000; 
	
#elif defined (SYSTEM_HCLK_48M_PCLK_48M)

	CSP_SCU_PLLEnable (SCU, XTAL8M_INPUT, PLLCON_PREDIV_DIV_BY_2, PLLCON_FBCTRL_12, 0); 	// (8/2 * 12)/1 = 64

	hclk_info = 50000000;
	pclk_info = 50000000; 
	
#elif defined (SYSTEMHCLK_32M_PCLK_32M)

	CSP_SCU_PLLEnable (SCU, XTAL8M_INPUT, PLLCON_PREDIV_DIV_BY_2, PLLCON_FBCTRL_16, 1); 	// (8/2 * 16)/2 = 32

	hclk_info = 32000000;
	pclk_info = 32000000; 
	
#elif defined (SYSTEM_HCLK_20M_PCLK_20M)

	CSP_SCU_PLLEnable (SCU, XTAL8M_INPUT, PLLCON_PREDIV_DIV_BY_2, PLLCON_FBCTRL_10, 1); 	// (8/2 * 10)/2 = 20

	hclk_info = 20000000;
	pclk_info = 20000000; 

#elif defined (SYSTEM_HCLK_16M_PCLK_16M)

	CSP_SCU_PLLEnable (SCU, XTAL8M_INPUT, PLLCON_PREDIV_DIV_BY_2, PLLCON_FBCTRL_12, 2); 	// (8/2 * 12)/3 = 16

	hclk_info = 16000000;
	pclk_info = 16000000; 
	
#endif 


	for (delay=0; delay<100; delay++); 


	//------------------------------------------------------------------------------------------
	// MCLK/HCLK/PCLK Setting
	//
	//				SCCR		@ address = 0x4000_0044
	//
	//------------------------------------------------------------------------------------------
	reg_val = CSP_SCU_GET_SCCR(SCU); 
	reg_val &= ~SCCR_MCLKSEL_MASK; 
	reg_val |= SCCR_MCLKSEL_PLL | SCCR_FINSEL_MOSC; 
	CSP_SCU_SET_SCCR(SCU, reg_val); 



	//------------------------------------------------------------------------------------------
	// Peripheral Enable 
	//
	//				PER1		@ address = 0x4000_0028
	//				PER2		@ address = 0x4000_002C
	//
	//				PCER1		@ address = 0x4000_0030
	//				PCER2		@ address = 0x4000_0034
	//
	//------------------------------------------------------------------------------------------	



	//------------------------------------------------------------------------------------------
	// BOD Setting 
	//
	//				BODCON		@ address = 0x4000_0068
	//
	//
	//------------------------------------------------------------------------------------------
	

#ifdef BOD_NOT_USE

	reg_val = (BODCON_SELEN|BODCON_BODEN_DISABLE); 

#elif defined (BOD_1_80V)

	reg_val = (BODCON_SELEN|BODCON_BODSEL_1_80V|BODCON_BODEN_ENABLE); 

#elif defined (BOD_2_20V)

	reg_val = (BODCON_SELEN|BODCON_BODSEL_2_20V|BODCON_BODEN_ENABLE); 

#elif defined (BOD_2_70V)

	reg_val = (BODCON_SELEN|BODCON_BODSEL_2_70V|BODCON_BODEN_ENABLE); 

#elif defined (BOD_4_30V)

	reg_val = (BODCON_SELEN|BODCON_BODSEL_4_30V|BODCON_BODEN_ENABLE); 

#endif 

	
	CSP_SCU_SET_BODCON(SCU, reg_val); 



	//------------------------------------------------------------------------------------------
	// Reset Setting 
	//
	//				RSER		@ address = 0x4000_0018
	//
	//
	//------------------------------------------------------------------------------------------
	CSP_SCU_SET_RSER(SCU, (RSER_PINRST|RSER_CORERST|RSER_WDTRST|RSER_LVDRST)); 


	//------------------------------------------------------------------------------------------
	// Clock Information Setting 
	//	
	//
	//------------------------------------------------------------------------------------------
	gSysClockInfo.HCLK = hclk_info; 
	gSysClockInfo.PCLK = pclk_info; 

}




/**
************************************************************************************
* @ Name : Init_BasicTimers
*
* @ Parameter
*		none
*
*
*
************************************************************************************
*/
void Init_BasicTimers (void)
{


	//======================================================================
	// 1 ms systick
	//
	//======================================================================
	CSP_SysTick_Init (SYSTICK, ST_CORE_CLOCK, 0, 0, 32000-1); 
	CSP_SysTick_ConfigureInterrupt(SYSTICK, ST_INTR_TICK, SYSINT_ENABLE); 


}



